An MCP formulation separates the transfer into two parts:

  1. Unsynchronized multi-bit data bus

    • The data signals are sent directly from the source domain to the destination domain — without synchronization.
    • The data is held stable for multiple destination clock cycles.
  2. Synchronized control signal

    • A single control signal (often a load, enable, or valid) is synchronized across the clock boundary using a two-flip-flop synchronizer.
    • This control signal tells the destination domain when to safely capture the data.

🧠 Key Principle

The receiving clock domain never samples the data until after the control signal has been fully synchronized.

Because the data remains stable for several destination cycles, the receiving register will always sample a stable, valid data word — never a transitioning one.


🔄 Timing Summary

Here’s how it works step-by-step:

  1. The source clock domain places a new data word (DATA[n:0]) on the CDC bus.
  2. The source then asserts an enable or load signal at the same time.
  3. The data remains unchanged for at least two cycles of the destination clock (to allow the enable to synchronize safely).
  4. After two synchronization stages in the destination domain, the enable signal becomes active (enable_sync).
  5. On the next rising edge of the destination clock, the receiving register captures the stable data.

📉 Simplified Timing Diagram

Source domain signals:
  DATA:   [==== D0 ====]               [==== D1 ====]
  ENABLE: ____|‾‾‾‾‾‾‾‾‾‾‾‾‾‾|__________

Destination domain (after 2FF synchronizer):
  ENABLE_SYNC: ________|‾‾‾‾‾‾‾‾|______
  CAPTURE:            ↑ (captures D0 safely)

Here, DATA is stable long before ENABLE_SYNC arrives — ensuring the data is captured correctly.


✅ Advantages

  1. No need to calculate pulse widths
    The source doesn’t need to stretch or time its pulses precisely relative to the destination clock (unlike open-loop approaches).

  2. Simplified control logic
    The enable signal doesn’t need to return low — it can remain high until the next data transaction.

  3. Safe multi-bit transfers
    The destination samples all bits simultaneously on one clock edge — avoiding skew or partial updates.

  4. No metastability in data
    Since data is stable when sampled, metastability risk is isolated to the control synchronizer only.


⚙️ Typical Implementation Example (Verilog)

Source Clock Domain

// Source domain logic
always @(posedge src_clk) begin
    if (send_new_data) begin
        data_bus <= next_data;  // Drive new data
        enable   <= 1'b1;       // Pulse or level change
    end
end

Destination Clock Domain

// Synchronize control signal
reg [1:0] enable_sync;
always @(posedge dest_clk) begin
    enable_sync <= {enable_sync[0], enable};
end

// Capture data after synchronization
always @(posedge dest_clk) begin
    if (enable_sync[1])
        dest_data <= data_bus;  // Data is stable and safe to sample
end

⚠️ Important Design Rules


🧩 Why It’s Called “Multi-Cycle Path”

Because the destination clock sees the data as valid and unchanged for multiple cycles before capture, the data path is allowed more than one cycle to settle.
In timing analysis terms, this path is declared as multi-cycle, meaning its setup requirement spans multiple destination cycles — consistent with how the logic actually operates.


🚀 Summary

Feature Description
Data Path Unsynchronized multi-bit data, held stable for multiple destination cycles
Control Path Single synchronized enable or load signal
Synchronization Depth Two-flip-flop synchronizer for control
Safety Guarantee Data always stable when sampled
Primary Use Case Multi-bit bus transfers (e.g., configuration words, FIFO interfaces)